/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** All rights reserved **
** **
** This program and the accompanying materials are made available under **
** the terms of the Eclipse Public License v1.0 which accompanies this **
** distribution, and is available at: **
** http://www.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.core.internal.persist.search;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.DateTools.Resolution;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.NumberTools;
import org.eclipse.core.runtime.Assert;
import org.rssowl.core.persist.IAttachment;
import org.rssowl.core.persist.ICategory;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.IPerson;
import org.rssowl.core.util.HTMLStripReader;
import java.io.StringReader;
import java.util.Date;
import java.util.List;
/**
* Base class for all {@link IEntity} based search documents in the fulltext
* index.
*
* @author ijuma
* @author bpasero
* @param <T> the {@link IEntity} that fills this document.
*/
public abstract class SearchDocument<T extends IEntity> {
/** The value of an Entitie's ID as integer */
protected static final int ENTITY_ID = -2;
/** The value of an Entitie's ID as String */
public static final String ENTITY_ID_TEXT = String.valueOf(ENTITY_ID);
private final Document fDocument;
private final T fType;
/**
* @param type the {@link IEntity} that fills this document.
*/
public SearchDocument(T type) {
Assert.isLegal(type != null);
fType = type;
fDocument = new Document();
}
/**
* @return the {@link IEntity} that fills this document.
*/
public final T getType() {
return fType;
}
/**
* @return the search document to be indexed.
*/
public final Document getDocument() {
return fDocument;
}
/**
* @return <code>true</code> if fields have been added and <code>false</code>
* otherwise.
*/
public abstract boolean addFields();
/**
* @param fields the list of fields to add to this document
* @return <code>true</code> if fields have been added and <code>false</code>
* otherwise.
*/
protected boolean addFieldsToDocument(List<Field> fields) {
if (fields.size() == 0)
return false;
for (Field field : fields) {
getDocument().add(field);
}
return true;
}
/**
* @param fields the list of fields to add to
* @param field the field to add
* @return <code>true</code> if fields have been added and <code>false</code>
* otherwise.
*/
protected boolean addField(List<Field> fields, Field field) {
if (field == null)
return false;
fields.add(field);
return true;
}
/**
* Creates a new <code>Field</code> representing the entities ID this Document
* wraps around.
*
* @return Field
*/
protected Field createDocumentIDField() {
return new Field(ENTITY_ID_TEXT, String.valueOf(getType().getId()), Store.YES, Index.UN_TOKENIZED);
}
/**
* Creates a new <code>Field</code> from the given ID value.
*
* @param fieldConstant the constant identifying the target field
* @param entity the entity the field is provided from
* @param store one of the {@link Store} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createIDField(int fieldConstant, IEntity entity, Store store) {
return new Field(String.valueOf(fieldConstant), String.valueOf(entity.getId()), store, Index.UN_TOKENIZED);
}
/**
* Creates a new <code>Field</code> from the given long value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createLongField(int fieldConstant, long value, Store store) {
String valueText = NumberTools.longToString(value);
return new Field(String.valueOf(fieldConstant), valueText, store, Index.UN_TOKENIZED);
}
/**
* Creates a new <code>Field</code> from the given boolean value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createBooleanField(int fieldConstant, boolean value, Store store) {
return new Field(String.valueOf(fieldConstant), String.valueOf(value), store, Index.UN_TOKENIZED);
}
/**
* Creates a new <code>Field</code> from the given Date value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createDateField(int fieldConstant, Date value, Store store) {
return createDateField(fieldConstant, value, store, Resolution.DAY);
}
/**
* Creates a new <code>Field</code> from the given Date value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @param resolution one of the {@link Resolution} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createDateField(int fieldConstant, Date value, Store store, Resolution resolution) {
if (value == null)
return null;
String valueText = DateTools.dateToString(value, resolution);
return new Field(String.valueOf(fieldConstant), valueText, store, Index.UN_TOKENIZED);
}
/**
* Creates a new <code>Field</code> from the given URI value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @param index one of the {@link Index} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createURIField(int fieldConstant, String value, Store store, Index index) {
if (value == null)
return null;
return new Field(String.valueOf(fieldConstant), value.toLowerCase(), store, index);
}
/**
* Creates a new <code>Field</code> from the given String value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @param index one of the {@link Index} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createStringField(int fieldConstant, String value, Store store, Index index) {
if (value == null)
return null;
return new Field(String.valueOf(fieldConstant), value, store, index);
}
/**
* Creates a new <code>Field</code> from the given String value containing
* HTML. The HTML will be stripped from the field and entities replaced. The
* value is <em>not stored</em>and <em>tokenized indexed</em>.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createHTMLField(int fieldConstant, String value) {
if (value == null)
return null;
return new Field(String.valueOf(fieldConstant), new HTMLStripReader(new StringReader(value)));
}
/**
* Creates a new <code>Field</code> from the given enum value.
*
* @param fieldConstant the constant identifying the target field
* @param value the value of the field
* @param store one of the {@link Store} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createEnumField(int fieldConstant, Enum<?> value, Store store) {
if (value == null)
return null;
return new Field(String.valueOf(fieldConstant), String.valueOf(value.ordinal()), store, Index.UN_TOKENIZED);
}
/**
* Creates a new <code>Field</code> from the given {@link IPerson}.
*
* @param fieldConstant the constant identifying the target field
* @param person the value of the field
* @param store one of the {@link Store} constants.
* @param index one of the {@link Index} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createPersonField(int fieldConstant, IPerson person, Store store, Index index) {
if (person == null)
return null;
/* Add Name and EMail */
if (person.getName() != null && person.getEmail() != null) {
return createStringField(fieldConstant, person.getName() + " " + person.getEmail().toString(), store, index); //$NON-NLS-1$
}
/* Add Name if present */
if (person.getName() != null)
return createStringField(fieldConstant, person.getName(), store, index);
/* Add EMail if present */
else if (person.getEmail() != null)
return createURIField(fieldConstant, person.getEmail().toString(), store, Index.UN_TOKENIZED);
return null;
}
/**
* Creates a new <code>Field</code> from the given list of {@link ICategory}.
*
* @param fieldConstant the constant identifying the target field
* @param categories the value of the field
* @param store one of the {@link Store} constants.
* @param index one of the {@link Index} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createCategoriesField(int fieldConstant, List<ICategory> categories, Store store, Index index) {
if (categories == null || categories.size() == 0)
return null;
/* Convert categories to a single String */
StringBuilder categoryValues = new StringBuilder();
for (ICategory category : categories) {
if (category.getName() != null)
categoryValues.append(category.getName()).append('\n');
}
if (categoryValues.length() > 0)
return createStringField(fieldConstant, categoryValues.toString(), store, index);
return null;
}
/**
* Creates a new <code>Field</code> from the given list of {@link IAttachment}
* .
*
* @param fieldConstant the constant identifying the target field
* @param attachments the value of the field
* @param store one of the {@link Store} constants.
* @param index one of the {@link Index} constants.
* @return Field the {@link Field} that can be used for indexing.
*/
protected Field createAttachmentsField(int fieldConstant, List<IAttachment> attachments, Store store, Index index) {
if (attachments == null || attachments.size() == 0)
return null;
/* Convert attachments to a single String */
StringBuilder attachmentValues = new StringBuilder();
for (IAttachment attachment : attachments) {
if (attachment.getLink() != null)
attachmentValues.append(attachment.getLink()).append(" "); //$NON-NLS-1$
if (attachment.getType() != null)
attachmentValues.append(attachment.getType()).append(" "); //$NON-NLS-1$
}
if (attachmentValues.length() > 0)
return createStringField(fieldConstant, attachmentValues.toString(), store, index);
return null;
}
}